
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <queue>
#include <omp.h>

#include <errno.h>
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>


#define  LOG_TAG    "OCV:libnative_activity"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)


using namespace std;
using namespace cv;

extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Sample4Mixed_FindFeatures(JNIEnv*, jobject, jlong addrin, jlong addrout, int select,int addwidth, int addheight);


JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Sample4Mixed_FindFeatures(JNIEnv*, jobject, jlong addrin, jlong addrout, int select,int addwidth, int addheight)
{

    Mat& mRgba = *(Mat*)addrin;
    Mat& mOutput = *(Mat*)addrout;
    int myselection = select;
    int mWidth= addwidth;
    int mHeight= addheight;

    vector<Vec3f> pfinal;
    Mat mRgbasplit [2];

    Scalar hsv_min = Scalar(0, 50, 50);
    Scalar hsv_max = Scalar(15, 255, 255);
    Scalar hsv_min2 = Scalar(175, 50, 50);
    Scalar hsv_max2 = Scalar(179, 255, 255);

    //double[] data=new double[3];
 // One way to select a range of colors by Hue



 //mRgba=mRgbasplit[0];

//Super switch
switch(myselection)
{

case 1:{


	//Traitement THRESHOLD uniquement
	Mat mHSV;
	Mat distance;
	Mat mThresholded;
	Mat mThresholded2;
	vector<Mat> lhsv;
    Mat array255(mHeight,mWidth,CV_8UC1);
	array255.setTo(Scalar(255));
	 cvtColor(mRgba, mHSV, COLOR_RGB2HSV);
	 inRange(mHSV, hsv_min, hsv_max, mThresholded);
	 inRange(mHSV, hsv_min2, hsv_max2, mThresholded2);
	 bitwise_or(mThresholded, mThresholded2, mThresholded);
	 split(mHSV, lhsv);
	 Mat S = lhsv[1];
	 Mat V = lhsv[2];
	 subtract(array255, S, S);
	 subtract(array255, V, V);
	 S.convertTo(S, CV_32F);
	 V.convertTo(V, CV_32F);
	 magnitude(S, V, distance);
	 inRange(distance,Scalar(0),Scalar(200), mThresholded2);
	 bitwise_and(mThresholded, mThresholded2, mOutput);
	}
break;

case 2:{
    Mat array255(mHeight,mWidth,CV_8UC1);
	array255.setTo(Scalar(255));
	Mat mHSV;
	Mat distance;
	Mat mThresholded;
	Mat mThresholded2;
	vector<Mat> lhsv;

	 cvtColor(mRgba, mHSV, COLOR_RGB2HSV);
	 inRange(mHSV, hsv_min, hsv_max, mThresholded);
	 inRange(mHSV, hsv_min2, hsv_max2, mThresholded2);
	 bitwise_or(mThresholded, mThresholded2, mThresholded);
	 split(mHSV, lhsv);
	 Mat S = lhsv[1];
	 Mat V = lhsv[2];
	 subtract(array255, S, S);
	 subtract(array255, V, V);
	 S.convertTo(S, CV_32F);
	 V.convertTo(V, CV_32F);
	 magnitude(S, V, distance);
	 inRange(distance,Scalar(0),Scalar(200), mThresholded2);
	 bitwise_and(mThresholded, mThresholded2, mThresholded);
	 dilate(mThresholded,mOutput,Mat(),Point(-1,-1),2,1,1);}

break;

default:
    Mat array255(mHeight,mWidth/2,CV_8UC1);
	array255.setTo(Scalar(255));
	mRgbasplit[0] = mRgba(Rect(0,0,mWidth/2,mHeight));
	mRgbasplit[1] = mRgba(Rect(mWidth/2,0,mWidth/2,mHeight));
	#pragma omp parallel for shared(pfinal)
	for(int p=0 ; p<2 ; p++)
		{
			Vec3f ptmp;
			Mat mHSV;
			Mat distance;
			Mat mThresholded;
			Mat mThresholded2;
			vector<Vec3f> circles;
			vector<Mat> lhsv;

			 cvtColor(mRgbasplit[p], mHSV, COLOR_RGB2HSV);
			 inRange(mHSV, hsv_min, hsv_max, mThresholded);
			 inRange(mHSV, hsv_min2, hsv_max2, mThresholded2);
			 bitwise_or(mThresholded, mThresholded2, mThresholded);
			 split(mHSV, lhsv);
			 Mat S = lhsv[1];
			 Mat V = lhsv[2];
			 subtract(array255, S, S);
			 subtract(array255, V, V);
			 S.convertTo(S, CV_32F);
			 V.convertTo(V, CV_32F);
			 magnitude(S, V, distance);
			 inRange(distance,Scalar(0),Scalar(200), mThresholded2);
			 bitwise_and(mThresholded, mThresholded2, mThresholded);
			 dilate(mThresholded,mThresholded,Mat(),Point(-1,-1),1,1,1);
			 GaussianBlur( mThresholded, mThresholded, Size(9, 9), 2, 2 );
			 HoughCircles(mThresholded, circles, CV_HOUGH_GRADIENT, 2, mHeight/4, 100, 50, 0, 0);
				 //Traitement des données, fin du traitement d'image
				  for( size_t i = 0; i < circles.size(); i++ )
				  {
					  if (p==1)
						  circles[i][0]+=mWidth/2;
					  Point center(cvRound((double)circles[i][0]), cvRound((double)circles[i][1]));
					  int radius = cvRound((double)circles[i][2]);
					  // circle center
					  circle( mRgba, center, 3, Scalar(0,255,0), -1, 8, 0 );
					  // circle outline
					  circle( mRgba, center, radius, Scalar(0,0,255), 3, 8, 0 );
				   }
				  if(!circles.empty())
				  {
					 float* p[circles.size()];
					 for( size_t j = 0; j < circles.size(); j++ )
					{
						 for( size_t i = 1; i < circles.size(); i++ )
						 {
							 if(cvRound(circles[i-1][2])<cvRound(circles[i][2]))
												{
													ptmp=circles[i-1];
													circles[i-1]=circles[i];
													circles[i]=ptmp;
												}
						 }
					}
					 pfinal.push_back(circles[0]);

				  }
		}

	if(pfinal.size()==2)
		LOGI("mesure gauche et droite %f et %f\n", pfinal[1][2], pfinal[0][2]);
break;



}
}

}
